cmake_minimum_required(VERSION 2.8)
project(lich4 C)

option(LVS "log structured volume" OFF)
option(spdk "Storage Performance Development Kit" OFF)
option(ec "Erasure Code" OFF)
option(nvmf "NVMe Over Fabraic" OFF)
option(libnvme "NVMe Over Fabraic" ON)
option(release "Release Mode" OFF)


# set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-as-needed")

# relative path

string(LENGTH "${CMAKE_SOURCE_DIR}/" SOURCE_PATH_SIZE)

add_definitions("-DCMAKE_SOURCE_PATH_SIZE=${SOURCE_PATH_SIZE}")

find_program(LSB_RELEASE lsb_release)

execute_process(COMMAND ${LSB_RELEASE} -si
    OUTPUT_VARIABLE LSB_RELEASE_ID
    OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${LSB_RELEASE} -sr
    OUTPUT_VARIABLE LSB_RELEASE_VER
    OUTPUT_STRIP_TRAILING_WHITESPACE)
message("LSB_RELEASE_ID ${LSB_RELEASE_ID}")
message("LSB_RELEASE_VER ${LSB_RELEASE_VER}")

if ("${LSB_RELEASE_ID}" STREQUAL "CentOS" AND ${LSB_RELEASE_VER} STRLESS "7.0")
    message("CMAKE_STATIC_ASSERT=0")
    add_definitions("-DCMAKE_STATIC_ASSERT=0")
else()
    message("CMAKE_STATIC_ASSERT=1")
    add_definitions("-DCMAKE_STATIC_ASSERT=1")
endif()

# set lich version
set (LICH_VERSION_MAJOR 1)
set (LICH_VERSION_MINOR 0)

# set install dir
set (LICH_HOME "/opt/fusionstack")
set (CMAKE_INSTALL_PREFIX "/opt/fusionstack")

set (LICH_SRC "${CMAKE_CURRENT_SOURCE_DIR}")

# set lsv dir
set (LSV_HOME "${CMAKE_SOURCE_DIR}/lsv")
set (LSV_SRC "${CMAKE_SOURCE_DIR}/lsv")

# set nvmf dir
set (NVMF_SRC "${CMAKE_SOURCE_DIR}/nvmf")

message("CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/")

message("CMAKE_SYSTEM_INFO_FILE ${CMAKE_SYSTEM_INFO_FILE}")
message("CMAKE_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}")
message("CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}")
message("CMAKE_SYSTEM ${CMAKE_SYSTEM}")

find_package(BISON)
find_package(FLEX)
find_package(Threads)
find_package(aio)

# add_subdirectory(${LICH_SRC}/config/lib)

#CREATE Files
add_custom_command(
    OUTPUT ${LICH_SRC}/build/confl.c
    COMMAND flex -o ${LICH_SRC}/build/confl.c ${LICH_SRC}/config/lib/confl.l
    DEPENDS ${LICH_SRC}/config/lib/confl.l
    )

add_custom_command(
    OUTPUT ${LICH_SRC}/build/confy.c ${LICH_SRC}/build/confy.h
    COMMAND bison -o ${LICH_SRC}/build/confy.c ${LICH_SRC}/config/lib/confy.y
    DEPENDS ${LICH_SRC}/config/lib/confy.y
    )

# ADD_INCLUDE_DIRECTORIES
include_directories(
    # ${LICH_SRC}/ylib/gdsl/include
    /usr/local/include
    #/usr/local/include/dpdk
    /usr/local/spdk-16.07/dpdk-16.07/include/dpdk

    ${LICH_SRC}/include
    ${LICH_SRC}/config/include
    ${LICH_SRC}/build
    ${LICH_SRC}/ylib/include
    ${LICH_SRC}/ynet/include
    ${LICH_SRC}/cluster/include
    ${LICH_SRC}/schedule
    ${LICH_SRC}/schedule/include
    ${LICH_SRC}/storage/lease
    ${LICH_SRC}/storage/storage
    ${LICH_SRC}/storage/controller
    ${LICH_SRC}/storage/chunk
    ${LICH_SRC}/storage/replica
    ${LICH_SRC}/storage/replica/diskmd
    ${LICH_SRC}/storage/replica/diskmd/disk
    ${LICH_SRC}/storage/replica/diskmd/disk_mapping
    ${LICH_SRC}/storage/task
    ${LICH_SRC}/storage/qos
    ${LICH_SRC}/lichd/include
    ${LICH_SRC}/test/include
    ${LICH_SRC}/nfs/include
    ${LICH_SRC}/iscsi/include
    ${LICH_SRC}/nbd/include
    ${LICH_SRC}/utils/include
    ${LICH_SRC}/libetcd
    ${LICH_SRC}/cbb/include
    ${CMAKE_CURRENT_BINARY_DIR}

    ${LICH_SRC}/protocol/fuse/include
    ${LICH_SRC}/protocol/sheepdog/include
    ${LICH_SRC}/protocol/sdk/c/include

    ${LSV_SRC}/include
    ${LSV_SRC}/src/wbuffer
    ${LSV_SRC}/src/rcache
    ${LSV_SRC}/src/bitmap
    ${LSV_SRC}/src/gc
    ${LSV_SRC}/src/log
    ${LSV_SRC}/src/volume
    ${LSV_SRC}/src/row2

    ${NVMF_SRC}/

    ${LICH_SRC}/libnvme/include
    ${LICH_SRC}/libnvme/include/libnvme
    ${LICH_SRC}/libnvme/common
    ${LICH_SRC}/libnvme/nvme
    )

# CREATE LIBRARY lich4
set(LICH4_SOURCE_FILES
    ${LICH_SRC}/config/lib/confl.l
    ${LICH_SRC}/config/lib/confy.y
    ${LICH_SRC}/config/lib/configure.c

    ${LICH_SRC}/build/confl.c
    ${LICH_SRC}/build/confy.c

    ${LICH_SRC}/ylib/lib/fastrandom.c
    ${LICH_SRC}/ylib/lib/sysutil.c
    ${LICH_SRC}/ylib/lib/mem_cache.c
    ${LICH_SRC}/ylib/lib/gettime.c
    ${LICH_SRC}/ylib/lib/job_dock.c
    ${LICH_SRC}/ylib/lib/mem_hugepage.c
    ${LICH_SRC}/ylib/lib/buffer.c
    ${LICH_SRC}/ylib/lib/cmp.c
    ${LICH_SRC}/ylib/lib/crc32.c
    ${LICH_SRC}/ylib/lib/crcrs.c
    ${LICH_SRC}/ylib/lib/daemon.c
    ${LICH_SRC}/ylib/lib/dbg.c
    ${LICH_SRC}/ylib/lib/hash.c
    ${LICH_SRC}/ylib/lib/hash_table.c
    ${LICH_SRC}/ylib/lib/lba_lock.c
    ${LICH_SRC}/ylib/lib/htable.c
    ${LICH_SRC}/ylib/lib/cache.c
    ${LICH_SRC}/ylib/lib/lock.c
    ${LICH_SRC}/ylib/lib/plock.c
    ${LICH_SRC}/ylib/lib/lba_lock.c
    ${LICH_SRC}/ylib/lib/redis_utils.c
    ${LICH_SRC}/ylib/lib/mem.c
    ${LICH_SRC}/ylib/lib/path.c
    ${LICH_SRC}/ylib/lib/stat.c
    ${LICH_SRC}/ylib/lib/skiplist.c
    ${LICH_SRC}/ylib/lib/timer.c
    ${LICH_SRC}/ylib/lib/xdr.c
    ${LICH_SRC}/ylib/lib/ylog.c
    ${LICH_SRC}/ylib/lib/ytime.c
    ${LICH_SRC}/ylib/lib/bmap.c
    ${LICH_SRC}/ylib/lib/md5.c
    ${LICH_SRC}/ylib/lib/squeue.c
    ${LICH_SRC}/ylib/lib/sequence.c
    ${LICH_SRC}/ylib/lib/analysis.c
    ${LICH_SRC}/ylib/lib/bh.c
    ${LICH_SRC}/ylib/lib/longtask.c
    ${LICH_SRC}/ylib/lib/fnotify.c
    ${LICH_SRC}/ylib/lib/worker.c
    ${LICH_SRC}/ylib/lib/yid.c
    ${LICH_SRC}/ylib/lib/tpool.c
    ${LICH_SRC}/ylib/lib/base64.c
    ${LICH_SRC}/ylib/lib/base64_urlsafe.c
    ${LICH_SRC}/ylib/lib/array_table.c
    ${LICH_SRC}/ylib/lib/token_bucket.c
    ${LICH_SRC}/ylib/lib/leaky_bucket.c
    ${LICH_SRC}/ylib/lib/rate_probe.c
    ${LICH_SRC}/ylib/lib/vec.c
    ${LICH_SRC}/ylib/lib/lru.c
    ${LICH_SRC}/ylib/lib/binn.c
    ${LICH_SRC}/ylib/lib/pool_list.c
    ${LICH_SRC}/ylib/lib/etcd.c
    ${LICH_SRC}/ylib/lib/buddy.c
    ${LICH_SRC}/ylib/lib/thread_pool.c
    ${LICH_SRC}/ylib/lib/str.c

    ${LICH_SRC}/memory/memory_pool.c
    ${LICH_SRC}/memory/memory_map.c
    ${LICH_SRC}/memory/memory_mr_map.c
    ${LICH_SRC}/memory/memory_scale.c
    ${LICH_SRC}/memory/memory_ring.c

    #${LICH_SRC}/libetcd/cJSON.c
    ${LICH_SRC}/libetcd/etcd-api.c
    ${LICH_SRC}/ylib/lib/lock_table.c
    ${LICH_SRC}/ylib/lib/cJSON.c

    # {{ GDSL
    # ${LICH_SRC}/ylib/gdsl/src/gdsl.c
    # ${LICH_SRC}/ylib/gdsl/src/gdsl_2darray.c
    # ${LICH_SRC}/ylib/gdsl/src/gdsl_list.c
    # ${LICH_SRC}/ylib/gdsl/src/gdsl_queue.c
    # ${LICH_SRC}/ylib/gdsl/src/gdsl_stack.c
    # ${LICH_SRC}/ylib/gdsl/src/gdsl_heap.c
    # ${LICH_SRC}/ylib/gdsl/src/gdsl_hash.c
    # ${LICH_SRC}/ylib/gdsl/src/gdsl_bstree.c
    # ${LICH_SRC}/ylib/gdsl/src/gdsl_rbtree.c

    # ${LICH_SRC}/ylib/gdsl/src/_gdsl_bintree.c
    # ${LICH_SRC}/ylib/gdsl/src/_gdsl_bstree.c
    # ${LICH_SRC}/ylib/gdsl/src/_gdsl_list.c
    # ${LICH_SRC}/ylib/gdsl/src/_gdsl_node.c
    # }}

    ${LICH_SRC}/ynet/sock/sock_buffer.c
    ${LICH_SRC}/ynet/sock/sock_passive.c
    ${LICH_SRC}/ynet/sock/sock_udp.c
    ${LICH_SRC}/ynet/sock/sock_xnect.c
    ${LICH_SRC}/ynet/sock/sock_xmit.c
    ${LICH_SRC}/ynet/sock/sdevent.c
    ${LICH_SRC}/ynet/sock/sock_unix.c
    ${LICH_SRC}/ynet/sock/sock_tcp.c
    ${LICH_SRC}/ynet/net/arp_host.c
    ${LICH_SRC}/ynet/net/hosts.c
    ${LICH_SRC}/ynet/net/net_lib.c
    ${LICH_SRC}/ynet/net/net_table.c
    ${LICH_SRC}/ynet/net/net_xmit.c
    ${LICH_SRC}/ynet/net/arp_lib.c
    ${LICH_SRC}/ynet/net/main_loop.c
    ${LICH_SRC}/ynet/net/net_msg.c
    ${LICH_SRC}/ynet/net/net_tool.c
    ${LICH_SRC}/ynet/net/libnetlink.c
    ${LICH_SRC}/ynet/net/fence.c
    ${LICH_SRC}/ynet/net/net_crc.c
    ${LICH_SRC}/ynet/net/net_passive.c
    ${LICH_SRC}/ynet/net/net_vip.c
    ${LICH_SRC}/ynet/net/xnect.c
    ${LICH_SRC}/ynet/net/heartbeat.c
    ${LICH_SRC}/ynet/net/net_events.c
    ${LICH_SRC}/ynet/net/net_rpc.c
    ${LICH_SRC}/ynet/net/net_crc.c
    ${LICH_SRC}/ynet/net/net_vip_rpc.c
    ${LICH_SRC}/ynet/net/conn.c
    ${LICH_SRC}/ynet/rpc/minirpc.c
    ${LICH_SRC}/ynet/rpc/rpc_lib.c
    ${LICH_SRC}/ynet/rpc/rpc_proto.c
    ${LICH_SRC}/ynet/rpc/rpc_request.c
    ${LICH_SRC}/ynet/rpc/msgqueue.c
    ${LICH_SRC}/ynet/rpc/rpc_passive.c
    ${LICH_SRC}/ynet/rpc/rpc_reply.c
    ${LICH_SRC}/ynet/rpc/rpc_table.c

    ${LICH_SRC}/schedule/schedule.c
    ${LICH_SRC}/schedule/schedule_thread.c
    ${LICH_SRC}/schedule/variable.c
    ${LICH_SRC}/schedule/cpuset.c
    ${LICH_SRC}/schedule/vm.c
    ${LICH_SRC}/schedule/core.c
    ${LICH_SRC}/schedule/corenet_tcp.c
    ${LICH_SRC}/schedule/corenet_rdma.c
    ${LICH_SRC}/schedule/corerpc.c
    ${LICH_SRC}/schedule/corenet_maping.c
    ${LICH_SRC}/schedule/corenet_connect_tcp.c
    ${LICH_SRC}/schedule/corenet_connect_rdma.c
    ${LICH_SRC}/schedule/aio.c
    ${LICH_SRC}/schedule/rdma_event.c

    ${LICH_SRC}/schedule/coroutine.c
    ${LICH_SRC}/schedule/co_mq.c

    ${LICH_SRC}/prof/prof_rpc.c
    ${LICH_SRC}/prof/prof_net.c
    ${LICH_SRC}/prof/prof_vm.c
    ${LICH_SRC}/prof/prof_lichbd.c
    ${LICH_SRC}/prof/prof_dio.c

    ${LICH_SRC}/cluster/node/node.c
    ${LICH_SRC}/cluster/node/nodectl.c
    ${LICH_SRC}/cluster/node/optconfig.c
    ${LICH_SRC}/cluster/node/node_srv.c
    ${LICH_SRC}/cluster/node/node_admin.c
    ${LICH_SRC}/cluster/node/node_rpc.c
    ${LICH_SRC}/cluster/node/env.c

    ${LICH_SRC}/cluster/cluster/cluster.c
    ${LICH_SRC}/cluster/cluster/cluster_rpc.c
    ${LICH_SRC}/cluster/cluster/maping.c
    ${LICH_SRC}/cluster/cluster/network.c
    ${LICH_SRC}/cluster/dispatch/dispatch_srv.c
    ${LICH_SRC}/cluster/dispatch/dispatch_rpc.c
    ${LICH_SRC}/cluster/dispatch/dispatch.c
    ${LICH_SRC}/cluster/nodepool/nodetable.c
    ${LICH_SRC}/cluster/nodepool/diskmap.c
    ${LICH_SRC}/cluster/nodepool/nodeid.c

    ${LICH_SRC}/storage/storage/vnode.c
    ${LICH_SRC}/storage/storage/stor.c
    ${LICH_SRC}/storage/storage/stor_rpc.c
    ${LICH_SRC}/storage/storage/locator_rpc.c
    ${LICH_SRC}/storage/storage/stor_root.c
    ${LICH_SRC}/storage/storage/system.c
    ${LICH_SRC}/storage/storage/local_vol.c
    ${LICH_SRC}/storage/storage/storage_status.c

    ${LICH_SRC}/storage/storage/md.c
    ${LICH_SRC}/storage/storage/md_root.c
    ${LICH_SRC}/storage/storage/md_map.c
    ${LICH_SRC}/storage/storage/md_chunk.c
    ${LICH_SRC}/storage/storage/md_parent.c

    ${LICH_SRC}/storage/lease/lease_ctl.c
    ${LICH_SRC}/storage/lease/lease.c

    ${LICH_SRC}/storage/controller/table_proto.c
    ${LICH_SRC}/storage/controller/table_xattr.c
    ${LICH_SRC}/storage/controller/table_snap.c
    ${LICH_SRC}/storage/controller/table1.c
    ${LICH_SRC}/storage/controller/table1_ext.c
    ${LICH_SRC}/storage/controller/table2.c

    ${LICH_SRC}/storage/controller/volume_proto.c
    ${LICH_SRC}/storage/controller/volume_proto_rep.c
    ${LICH_SRC}/storage/controller/volume_proto_inf.c
    #${LICH_SRC}/storage/controller/volume_proto_readcache.c
    ${LICH_SRC}/storage/controller/volume_proto_io.c
    ${LICH_SRC}/storage/controller/volume_remote_io.c
    ${LICH_SRC}/storage/controller/volume_proto_analysis.c
    ${LICH_SRC}/storage/controller/volume_proto_latency.c
    ${LICH_SRC}/storage/controller/volume_proto_snapshot.c

    ${LICH_SRC}/storage/controller/stor_ctl.c
    ${LICH_SRC}/storage/controller/pool_proto.c
    ${LICH_SRC}/storage/controller/pool_rename.c
    ${LICH_SRC}/storage/controller/pool_ctl.c
    ${LICH_SRC}/storage/controller/volume_ctl.c
    ${LICH_SRC}/storage/controller/volume_ctl_internal.c
    ${LICH_SRC}/storage/controller/volume_ctl_cleanup.c
    ${LICH_SRC}/storage/controller/volume_ctl_rollback.c
    ${LICH_SRC}/storage/controller/volume_ctl_flat.c
    ${LICH_SRC}/storage/controller/volume_ctl_sync.c
    ${LICH_SRC}/storage/controller/castoff.c
    ${LICH_SRC}/storage/controller/ramdisk.c

    # Async Tasks
    ${LICH_SRC}/storage/storage/volume.c
    ${LICH_SRC}/storage/controller/volume_bh.c
    ${LICH_SRC}/storage/controller/pool_rmvol.c

    ${LICH_SRC}/storage/bhtask/transaction.c
    ${LICH_SRC}/storage/bhtask/bh_task.c
    ${LICH_SRC}/storage/bhtask/rmvol_bh.c
    ${LICH_SRC}/storage/bhtask/rmsnap_bh.c
    # ${LICH_SRC}/storage/bhtask/rollback_bh.c
    ${LICH_SRC}/storage/bhtask/etcd_task.c

    ${LICH_SRC}/storage/chunk/chunk_cleanup.c
    ${LICH_SRC}/storage/chunk/chunk_bh.c
    ${LICH_SRC}/storage/chunk/chunk_sync.c
    ${LICH_SRC}/storage/chunk/chunk_proto.c
    ${LICH_SRC}/storage/chunk/chunk_proto_rep.c

    ${LICH_SRC}/storage/replica/replica_srv.c
    ${LICH_SRC}/storage/replica/replica_write.c
    ${LICH_SRC}/storage/replica/replica_read.c
    ${LICH_SRC}/storage/replica/replica_sync.c
    ${LICH_SRC}/storage/replica/replica_rpc.c
    ${LICH_SRC}/storage/replica/replica_cleanup.c

    ${LICH_SRC}/storage/replica/clock/clock.c
    ${LICH_SRC}/storage/replica/clock/clock_mem.c
    ${LICH_SRC}/storage/replica/clock/clock_merge.c

    ${LICH_SRC}/storage/replica/diskmd/diskmd.c
    ${LICH_SRC}/storage/replica/diskmd/diskmd_async.c
    ${LICH_SRC}/storage/replica/diskmd/diskmd_pool.c
    ${LICH_SRC}/storage/replica/diskmd/disk_slot.c
    #${LICH_SRC}/storage/replica/diskmd/diskmd_allocate.c
    
    ${LICH_SRC}/storage/replica/diskmd/disk/disk.c
    ${LICH_SRC}/storage/replica/diskmd/disk/disk_normal.c
    ${LICH_SRC}/storage/replica/diskmd/disk/disk_ram.c

    ${LICH_SRC}/storage/replica/diskmd/disk_mapping/disk_sqlite3.c
    ${LICH_SRC}/storage/replica/diskmd/disk_mapping/disk_sqlite3_vacuum.c
    ${LICH_SRC}/storage/replica/diskmd/disk_mapping/disk_sqlite3_loadmulti.c
    ${LICH_SRC}/storage/replica/diskmd/disk_mapping/disk_sqlite3_createmulti.c
    ${LICH_SRC}/storage/replica/diskmd/disk_mapping/disk_redis.c
    ${LICH_SRC}/storage/replica/diskmd/disk_mapping/disk_maping.c

    ${LICH_SRC}/storage/task/utils.c
    ${LICH_SRC}/storage/task/recovery.c
    ${LICH_SRC}/storage/task/recovery_config.c
    ${LICH_SRC}/storage/task/recovery_flag.c
    ${LICH_SRC}/storage/task/recovery_qos.c
    ${LICH_SRC}/storage/task/recovery_tp.c
    ${LICH_SRC}/storage/task/recovery_out.c
    ${LICH_SRC}/storage/task/diskmd_recovery.c

    ${LICH_SRC}/storage/task/balance2.c
    ${LICH_SRC}/storage/task/balance_pool.c
    ${LICH_SRC}/storage/task/balance_utils.c
    ${LICH_SRC}/storage/task/config.c

    ${LICH_SRC}/storage/qos/lich_qos.c
    ${LICH_SRC}/storage/qos/volume_proto_qos.c

    ${LICH_SRC}/nbd/src/nbd_srv.c
    ${LICH_SRC}/lichbd/lichbd.c
    ${LICH_SRC}/lichbd/lichbd_rpc.c

    ${LICH_SRC}/iscsi/src/block.c
    ${LICH_SRC}/iscsi/src/iscsid.c
    ${LICH_SRC}/iscsi/src/iscsi_mem_cache.c
    ${LICH_SRC}/iscsi/src/digest.c
    ${LICH_SRC}/iscsi/src/ua.c
    ${LICH_SRC}/iscsi/src/iscsi_md5.c
    ${LICH_SRC}/iscsi/src/tio.c
    ${LICH_SRC}/iscsi/src/config.c
    ${LICH_SRC}/iscsi/src/lich_io.c
    ${LICH_SRC}/iscsi/src/sha1.c
    ${LICH_SRC}/iscsi/src/conn.c
    ${LICH_SRC}/iscsi/src/chap.c
    ${LICH_SRC}/iscsi/src/session.c
    ${LICH_SRC}/iscsi/src/target_disk.c
    ${LICH_SRC}/iscsi/src/iscsi.c
    ${LICH_SRC}/iscsi/src/param.c
    ${LICH_SRC}/iscsi/src/target.c
    ${LICH_SRC}/iscsi/src/vol.c
    ${LICH_SRC}/iscsi/src/iscsi_worker.c
    ${LICH_SRC}/iscsi/src/debug.c
    ${LICH_SRC}/iscsi/src/cmds.c
    ${LICH_SRC}/iscsi/src/iscsi_copy_mgr.c
    ${LICH_SRC}/iscsi/src/unmap.c

    ${LICH_SRC}/cbb/src/hostmap.c
    ${LICH_SRC}/cbb/src/cleanup_offline_msg.c

    ${LICH_SRC}/iscsi/iser/iser.c 
    # ${LICH_SRC}/iscsi/iser/event.c 
    ${LICH_SRC}/iscsi/iser/iser_conn.c 
    ${LICH_SRC}/iscsi/iser/iser_device.c 
    ${LICH_SRC}/iscsi/iser/iser_rdma.c 
    ${LICH_SRC}/iscsi/iser/iser_sched.c 
    ${LICH_SRC}/iscsi/iser/iser_cmds.c 
    ${LICH_SRC}/iscsi/iser/iser_text.c 
    ${LICH_SRC}/iscsi/iser/iser_task.c

    #replication....
    ${LICH_SRC}/replication/iscsi/connect.c      
    ${LICH_SRC}/replication/iscsi/crc32c.c
    ${LICH_SRC}/replication/iscsi/discovery.c
    ${LICH_SRC}/replication/iscsi/init.c
    ${LICH_SRC}/replication/iscsi/iscsi-command.c
    ${LICH_SRC}/replication/iscsi/iser.c
    ${LICH_SRC}/replication/iscsi/logging.c
    ${LICH_SRC}/replication/iscsi/login.c
    #${LICH_SRC}/replication/iscsi/md5.c
    ${LICH_SRC}/replication/iscsi/nop.c
    ${LICH_SRC}/replication/iscsi/pdu.c
    ${LICH_SRC}/replication/iscsi/scsi-lowlevel.c
    ${LICH_SRC}/replication/iscsi/socket.c
    ${LICH_SRC}/replication/iscsi/sync.c
    ${LICH_SRC}/replication/iscsi/task_mgmt.c

    ##############################################
    # SDK/C
    ##############################################
    ${LICH_SRC}/protocol/sdk/c/src/fstor.c

    ${LICH_SRC}/protocol/sheepdog/src/sheepdog.c
    ${LICH_SRC}/protocol/sheepdog/src/sd_map.c
    ##############################################
    # LSV
    ##############################################
    ${LSV_SRC}/src/lib/lsv_lib.c
    ${LSV_SRC}/src/lib/lsv_page.c

    ${LSV_SRC}/src/wbuffer/align_io.c
    # ${LSV_SRC}/src/wbuffer/lock_table.c
    ${LSV_SRC}/src/wbuffer/commit_order.c

    ${LSV_SRC}/src/wbuffer/lsv_wbuffer.c
    ${LSV_SRC}/src/wbuffer/lsv_wbuffer_internal.c
    #${LSV_SRC}/src/wbuffer/lsv_wbuffer_wal.c
    #${LSV_SRC}/src/wbuffer/lsv_wbuffer_wal2.c
    ${LSV_SRC}/src/wbuffer/lsv_wbuffer_wal2_segment.c
    #${LSV_SRC}/src/wbuffer/lsv_wbuffer_segment.c
    #${LSV_SRC}/src/wbuffer/lsv_wbuffer_index.c
    ${LSV_SRC}/src/wbuffer/lsv_wbuffer_chunk.c
    ${LSV_SRC}/src/wbuffer/lsv_wbuffer_chunk_index.c
    ${LSV_SRC}/src/wbuffer/lsv_wbuffer_pipeline.c
    ${LSV_SRC}/src/wbuffer/lsv_wbuffer_qos.c

    ${LSV_SRC}/src/rcache/lsv_rcache.c
    ${LSV_SRC}/src/rcache/lsv_rcache_index.c
    ${LSV_SRC}/src/rcache/lsv_rcache_page.c
    ${LSV_SRC}/src/rcache/lsv_rcache_pages.c
    ${LSV_SRC}/src/rcache/lsv_rcache_chunk.c
    ${LSV_SRC}/src/rcache/lsv_rcache_rw.c
    ${LSV_SRC}/src/rcache/lsv_rcache_l2_cache.c
    # ${LSV_SRC}/src/rcache/lsv_rcache_v2.c

    ${LSV_SRC}/src/bitmap/lsv_bitmap.c
    ${LSV_SRC}/src/bitmap/row2_bitmap.c
    ${LSV_SRC}/src/bitmap/lsv_bitmap_io.c
    ${LSV_SRC}/src/bitmap/lsv_bitmap_snap.c
    ${LSV_SRC}/src/bitmap/lsv_bitmap_cache.c
    ${LSV_SRC}/src/bitmap/lsv_bitmap_hash_cache.c
    #${LSV_SRC}/src/bitmap/lsv_bitmap_hash_cache2.c
    ## ${LSV_SRC}/src/bitmap/lsv_bitmap_index.c

    ${LSV_SRC}/src/log/lsv_log.c

    ${LSV_SRC}/src/gc/lsv_gc.c
    ${LSV_SRC}/src/gc/lsv_gc_stat.c
    ${LSV_SRC}/src/gc/lsv_gc_task.c
    ${LSV_SRC}/src/gc/lsv_gc_logctrl.c
    ${LSV_SRC}/src/gc/lsv_gc_check_queue.c
    ${LSV_SRC}/src/gc/lsv_gc_valueup.c
    ${LSV_SRC}/src/gc/lsv_gc_heap.c
    ${LSV_SRC}/src/gc/lsv_gc_old_storage.c
    ${LSV_SRC}/src/gc/lsv_gc_bitmap.c
    ${LSV_SRC}/src/gc/lsv_gc_fullgc.c

    ${LSV_SRC}/src/volume/lsv_volume.c
    ${LSV_SRC}/src/volume/lsv_volume_gc.c
    ${LSV_SRC}/src/chunkmap/chunkmap.c
    ${LSV_SRC}/src/volume/lsv_volume_bitmap.c
    ${LSV_SRC}/src/volume/lsv_volume_pool.c
    #${LSV_SRC}/src/volume/lsv_volume_file_impl.c
    ${LSV_SRC}/src/volume/lsv_volume_lich_impl.c

    ${LSV_SRC}/src/lsv/lsv_info.c
    ${LSV_SRC}/src/lsv/lsv_volume_proto_io.c
    ${LSV_SRC}/src/lsv/lsv_volume_proto_snapshot.c

    ${LSV_SRC}/src/row2/row2_info.c
    ${LSV_SRC}/src/row2/row2_consist_checker.c
    ${LSV_SRC}/src/row2/row2_volume_proto_io.c

    ${LSV_SRC}/src/row2/row3_info.c
    ${LSV_SRC}/src/row2/row3_volume_proto_io.c
    ${LSV_SRC}/src/row2/row_low_tlb_io.c
)

set(NFS_SOURCE_FILES
    ${LICH_SRC}/nfs/src/sunrpc_passive.c
    ${LICH_SRC}/nfs/src/sunrpc_reply.c
    ${LICH_SRC}/nfs/src/sunrpc_proto.c
    ${LICH_SRC}/nfs/src/attr.c
    ${LICH_SRC}/nfs/src/error.c
    ${LICH_SRC}/nfs/src/readdir.c
    ${LICH_SRC}/nfs/src/nfs_events.c
    ${LICH_SRC}/nfs/src/mountlist.c
    ${LICH_SRC}/nfs/src/nfs_state_machine.c
    ${LICH_SRC}/nfs/src/xdr_nfs.c
    ${LICH_SRC}/nfs/src/nfs_proc.c
    ${LICH_SRC}/nfs/src/nfs_srv.c
)

if(${spdk} STREQUAL "ON")
    message("***************SPDK is enabled.***************")
    ADD_DEFINITIONS(-DSPDK)
    set(SPDK_SOURCE_FILES
        ${LICH_SRC}/schedule/spdk.c
        ${LICH_SRC}/ylib/lib/buffer_sgl.c
        ${LICH_SRC}/storage/replica/diskmd/disk/disk_spdk.c
    )
    set (SPDK_LIBS spdk_nvme spdk_util spdk_memory pciaccess spdk_env spdk_log rte_mempool rte_eal rte_ring)
endif()

if(${libnvme} STREQUAL "ON")
    message("***************libnvme is enabled.***************")
    set (LIBNVME_SRC "${CMAKE_SOURCE_DIR}/libnvme")
    add_definitions(-DLIBNVME)
    file(GLOB_RECURSE LIBNVME_SOURCE_FILES
        "${LIBNVME_SRC}/common/*"
        "${LIBNVME_SRC}/nvme/*"
        "${LIBNVME_SRC}/info/*"
        "${LICH_SRC}/storage/replica/diskmd/disk_nvme.c"
    )
    set (LIBNVME_LIBS pciaccess numa)
endif()

if(${ec} STREQUAL "ON")
    message("***************EC is enabled.***************")
    set(EC_SOURCE_FILES
        ${LICH_SRC}/ylib/lib/ec_isa_l.c
        ${LICH_SRC}/storage/chunk/chunk_proto_ec.c
        ${LICH_SRC}/storage/controller/volume_proto_ec.c
        ${LICH_SRC}/storage/controller/volume_proto_eclog.c
    )
    set (EC_LIBS isal)
endif()

if(${nvmf} STREQUAL "ON")
    message("***************NVMF is enabled.***************")
    ADD_DEFINITIONS(-DNVMF)
    file(GLOB_RECURSE NVMF_SOURCE_FILES "${NVMF_SRC}/*.c")
endif()

#add_library(lich4s SHARED
add_library(lich4s STATIC
    ${LICH4_SOURCE_FILES}
    ${SPDK_SOURCE_FILES}
    ${EC_SOURCE_FILES}
    ${NVMF_SOURCE_FILES}
    ${LIBNVME_SOURCE_FILES}
)

if (EXISTS "${CMAKE_SOURCE_DIR}/__testing__")
    set(NO_WARN "-Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wno-unused-but-set-variable -Wno-sign-compare -Wno-pointer-sign")
else()
    set(NO_WARN " -Wunused-parameter")
endif()

if(${release} STREQUAL "ON")
    message("***************Build for release.***************")
    message("use:")
    message("objcopy --only-keep-debug bin sym")
    message("strip --strip-debug --strip-unneeded bin")
    message("objcopy --add-gnu-debuglink=sym bin")

    set (CMAKE_C_FLAGS "-std=c99 -fms-extensions -gsplit-dwarf -O3 ${NO_WARN} -Wno-unused-function -D_GNU_SOURCE -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D_REENTRANT -D_FILE_OFFSET_BITS=64 -m64 -mssse3 -D_GNU_SOURCE -D_REENTRANT")
else()
    set (CMAKE_C_FLAGS "-std=c99 -fms-extensions -g -Wall -Werror ${NO_WARN} -Wno-unused-function -Wno-unused-parameter -Wno-format-truncation -Wno-format-overflow -Wno-deprecated-declarations -Wno-misleading-indentation -fPIC -rdynamic -D_GNU_SOURCE -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D_REENTRANT -D_FILE_OFFSET_BITS=64 -m64 -mssse3 -D_GNU_SOURCE -D_REENTRANT")
endif()

#set (CMAKE_C_FLAGS "-std=c99 -fms-extensions -g -Wall -Werror ${NO_WARN} -fPIC -rdynamic -D_GNU_SOURCE -D_REENTRANT -D_FILE_OFFSET_BITS=64")
#set (CMAKE_C_FLAGS "-std=c99 -fms-extensions -g -Wall -Werror ${NO_WARN} -fPIC -rdynamic -DRDMA_SPDK -D_GNU_SOURCE -D_REENTRANT -D_FILE_OFFSET_BITS=64 -m64 -mssse3 -W -Wall -D_GNU_SOURCE -D_REENTRANT -DHAVE_CONFIG_H -MD -MP -MF")
#set (CMAKE_C_FLAGS "-std=c99 -fms-extensions -g -Wall -Werror -Wno-unused-function -Wno-unused-parameter -fPIC -rdynamic -D_GNU_SOURCE -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D_REENTRANT -D_FILE_OFFSET_BITS=64 -m64 -mssse3 -D_GNU_SOURCE -D_REENTRANT")

set (EXTERNAL_LIBS pthread crypt crypto uuid aio ssl rt sqlite3 ibverbs rdmacm m hiredis curl yajl numa ${EC_LIBS} ${SPDK_LIBS} ${LIBNVME_LIBS})
set (CMAKE_C_LIBS lich4s ${EXTERNAL_LIBS})

target_link_libraries(lich4s ${EXTERNAL_LIBS})

#SET_TARGET_PROPERTIES(lich4 PROPERTIES COMPILE_FLAGS " -laio")

SET_TARGET_PROPERTIES(lich4s PROPERTIES OUTPUT_NAME lich4s CLEAN_DIRECT_OUTPUT 1)

LINK_DIRECTORIES("/usr/local/lib")

set(LICHD_SRC_LIST
    ${LICH_SRC}/lichd/src/main.c
    )
add_executable(lichd ${LICHD_SRC_LIST})
target_link_libraries(lichd ${CMAKE_C_LIBS})

set(LICHGW_SRC_LIST
    ${LICH_SRC}/lichd/src/gateway.c
    )
add_executable(lichgw ${LICHGW_SRC_LIST})
target_link_libraries(lichgw ${CMAKE_C_LIBS})


set(LICH_ADMIN_SRC_LIST
    ${LICH_SRC}/utils/src/lich.admin.c
    ${LICH_SRC}/utils/src/attr.c
    ${LICH_SRC}/utils/src/utils.c
    ${LICH_SRC}/utils/src/spare.c
    ${LICH_SRC}/utils/src/md5sum.c
    )
add_executable(lich.admin ${LICH_ADMIN_SRC_LIST})
target_link_libraries(lich.admin ${CMAKE_C_LIBS})


set(LICH_PROF_SRC_LIST
    ${LICH_SRC}/utils/src/lich.prof.c
    )
add_executable(lich.prof ${LICH_PROF_SRC_LIST})
target_link_libraries(lich.prof ${CMAKE_C_LIBS})

#set(LICH_HELLO_CPP_SRC_LIST
#    ${LICH_SRC}/utils/src/lich.hello.cpp
#    )
#add_executable(lich.hello ${LICH_HELLO_CPP_SRC_LIST})
#target_link_libraries(lich.hello ${CMAKE_C_LIBS})


set (LICH_INSPECT_SRC_LIST
    ${LICH_SRC}/utils/src/lich.inspect.c
    ${LICH_SRC}/utils/src/recovery.c
    ${LICH_SRC}/utils/src/md5sum.c
    ${LICH_SRC}/utils/src/license.c
    ${LICH_SRC}/utils/src/attr.c
    ${LICH_SRC}/utils/src/utils.c
    ${LICH_SRC}/utils/src/spare.c
    )
add_executable(lich.inspect ${LICH_INSPECT_SRC_LIST})
target_link_libraries(lich.inspect ${CMAKE_C_LIBS})


set(LICHFS_SRC_LIST
    ${LICH_SRC}/utils/src/lich.fs.c
    ${LICH_SRC}/utils/src/attr.c
    ${LICH_SRC}/utils/src/copy.c
    ${LICH_SRC}/utils/src/license.c
    ${LICH_SRC}/utils/src/utils.c
    ${LICH_SRC}/utils/src/spare.c
    ${LICH_SRC}/utils/src/md5sum.c
    )
add_executable(lichfs ${LICHFS_SRC_LIST})
target_link_libraries(lichfs ${CMAKE_C_LIBS})

set(CLOCK_TEST_SRC_LIST
    ${LICH_SRC}/storage/tests/test_clock.c
    )
add_executable(test_clock ${CLOCK_TEST_SRC_LIST})
target_link_libraries(test_clock ${CMAKE_C_LIBS})

set(MSGQUEUE_TEST_SRC_LIST
    ${LICH_SRC}/ynet/tests/msgqueue_test.c
    )
add_executable(msgqueue_test ${MSGQUEUE_TEST_SRC_LIST})
target_link_libraries(msgqueue_test ${CMAKE_C_LIBS})

set(TEST_GEN_TEST_SRC_LIST
    ${LICH_SRC}/test/src/test_gen.c
    )
add_executable(test_gen_test ${TEST_GEN_TEST_SRC_LIST})
target_link_libraries(test_gen_test ${CMAKE_C_LIBS})



#set(LICH_FUSE_SRC_LIST
#    ${CMAKE_CURRENT_SOURCE_DIR}/fuse/src/file_table.c
#    ${CMAKE_CURRENT_SOURCE_DIR}/fuse/src/pfs.c
#    ${CMAKE_CURRENT_SOURCE_DIR}/fuse/src/main.c
#)
#add_executable(lich.fuse ${LICH_FUSE_SRC_LIST})
#target_link_libraries(lich.fuse ${CMAKE_C_LIBS})


set(LICHBD_SRC_LIST
    ${LICH_SRC}/utils/src/lichbd_utils.c
    ${LICH_SRC}/utils/src/attr.c
    ${LICH_SRC}/utils/src/copy.c
    ${LICH_SRC}/utils/src/license.c
    ${LICH_SRC}/utils/src/utils.c
    ${LICH_SRC}/utils/src/option.c
    ${LICH_SRC}/utils/src/spare.c
    ${LICH_SRC}/utils/src/md5sum.c
    ${LICH_SRC}/utils/src/auth.c
    )
add_executable(lichbd ${LICHBD_SRC_LIST})
target_link_libraries(lichbd ${CMAKE_C_LIBS})


set(LICH_SNAPSHOT_SRC_LIST
    ${LICH_SRC}/utils/src/lich.snapshot.c
    ${LICH_SRC}/utils/src/attr.c
    ${LICH_SRC}/utils/src/license.c
    ${LICH_SRC}/utils/src/utils.c
    ${LICH_SRC}/utils/src/spare.c
    ${LICH_SRC}/utils/src/md5sum.c
    )
add_executable(lich.snapshot ${LICH_SNAPSHOT_SRC_LIST})
target_link_libraries(lich.snapshot ${CMAKE_C_LIBS})


set(LICH_LICENSE_SRC_LIST
    ${LICH_SRC}/utils/src/lich.license.c
    ${LICH_SRC}/utils/src/license.c
    )
add_executable(lich.license ${LICH_LICENSE_SRC_LIST})
target_link_libraries(lich.license ${CMAKE_C_LIBS})


set(LICH_LICENSE_GEN_SRC_LIST
    ${LICH_SRC}/utils/src/lich.license_gen.c
    ${LICH_SRC}/utils/src/license.c
    )
add_executable(lich.license_gen ${LICH_LICENSE_GEN_SRC_LIST})
target_link_libraries(lich.license_gen ${CMAKE_C_LIBS})


set(LICH_ARP_SRC_LIST
    ${LICH_SRC}/arp/lich_arp.c
    )
add_executable(lich_arp ${LICH_ARP_SRC_LIST})

# install
#install(TARGETS lich4  ARCHIVE DESTINATION lich/lib)
#install(TARGETS lich4s LIBRARY DESTINATION lich/lib)
install(TARGETS lich4s  ARCHIVE DESTINATION lich/lib)

install(TARGETS lichd  RUNTIME DESTINATION lich/sbin)
install(TARGETS lichgw  RUNTIME DESTINATION lich/sbin)
install(TARGETS lichbd RUNTIME DESTINATION lich/libexec)
install(TARGETS lichfs RUNTIME DESTINATION lich/libexec)
install(TARGETS lich.snapshot RUNTIME DESTINATION lich/libexec)
#install(TARGETS lich.fuse RUNTIME DESTINATION lich/libexec)
install(TARGETS lich.admin RUNTIME DESTINATION lich/libexec)
install(TARGETS lich.inspect RUNTIME DESTINATION lich/libexec)
install(TARGETS lich.prof RUNTIME DESTINATION lich/libexec)
install(TARGETS lich.license RUNTIME DESTINATION lich/libexec)
install(TARGETS lich.license_gen RUNTIME DESTINATION lich/libexec)
install(TARGETS lich_arp RUNTIME DESTINATION lich/libexec)

install(DIRECTORY DESTINATION lich/bin)
install(DIRECTORY ${LICH_SRC}/admin DESTINATION lich FILE_PERMISSIONS OWNER_EXECUTE GROUP_EXECUTE WORLD_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)

if (NOT EXISTS "${LICH_HOME}/etc/lich.conf")
    message("Notes: check lich.conf is exists only work for `cmake ..', not `make install'")
    install(FILES ${LICH_SRC}/etc/lich.conf DESTINATION etc)
endif()

install(FILES ${LICH_SRC}/etc/lich.conf.example DESTINATION etc)
install(FILES ${LICH_SRC}/etc/cache.conf.example DESTINATION etc)
install(FILES ${LICH_SRC}/etc/hosts.conf DESTINATION etc)
install(FILES ${LICH_SRC}/etc/ssd.models DESTINATION etc)
install(FILES ${LICH_SRC}/etc/redis.conf DESTINATION etc)
# install(FILES ${LICH_SRC}/etc/ld_lich4.conf DESTINATION /etc/ld.so.conf.d/)

# SNMP
# install(FILES ${LICH_SRC}/whitebox/snmp/mibs/ietf/SNMPv2-MIB DESTINATION etc/mibs/ietf)
# install(FILES ${LICH_SRC}/whitebox/snmp/mibs/ietf/HOST-RESOURCES-MIB DESTINATION etc/mibs/ietf)
# install(FILES ${LICH_SRC}/whitebox/snmp/mibs/ietf/ENTITY-MIB DESTINATION etc/mibs/ietf)

# TODO: variables
install(CODE "set(PROJECT_HOME \"${CMAKE_SOURCE_DIR}\")")
install(CODE "set(LICH_HOME \"${LICH_HOME}\")")
install(SCRIPT ${CMAKE_SOURCE_DIR}/cmake/Install.cmake)

# ADD_TARGET
add_custom_target(autogen
    COMMAND ./tools/autogen.sh
    WORKING_DIRECTORY ${LICH_SRC}
    )

add_custom_target(conf
    COMMAND CFLAGS="-g" ./tools/lichconf.sh "--prefix=${CMAKE_INSTALL_PREFIX}/lich" "sysconfdir=${CMAKE_INSTALL_PREFIX}/etc" ;
    WORKING_DIRECTORY ${LICH_SRC}
    )

add_custom_target(version
    COMMAND ./tools/get_version.sh
    WORKING_DIRECTORY ${LICH_SRC}
    )

add_custom_target(tar
    COMMAND ./tools/app_tar.sh "${CMAKE_INSTALL_PREFIX}/lich"
    WORKING_DIRECTORY ${LICH_SRC}
    )

add_dependencies(lich4s version)

#add_custom_target(clean
#        COMMAND make -C build clean
#        COMMAND make -C include clean
#        WORKING_DIRECTORY ${LICH_SRC}
#        )

#add_custom_target(distclean
#        COMMAND cd make -C build distclean
#        COMMAND cd make -C include distclean
#        WORKING_DIRECTORY ${LICH_SRC}
#        )

#add_custom_target(uninstall
#   COMMAND if  cmp -s $(CMAKE_INSTALL_PREFIX)/etc/lich.conf ${LICH_SRC}/etc/lich.conf;
#              then \
#                echo "${CMAKE_INSTALL_PREFIX}/etc/lich.conf is not changed and will be removed."; \
#                rm -f ${CMAKE_INSTALL_PREFIX}/etc/lich.conf; \
#           fi
#   COMMAND if cmp -s $(CMAKE_INSTALL_PREFIX)/etc/hosts.conf ${LICH_SRC}/etc/hosts.conf; then \
#                echo "${CMAKE_INSTALL_PREFIX}/etc/hosts.conf is not changed and will be removed."; \
#                rm -f ${CMAKE_INSTALL_PREFIX}/etc/hosts.conf; \
#           fi
#   WORKING_DIRECTORY ${LICH_SRC}
#)

# add_subdirectory(lsv)
